import { _decorator, Component } from 'cc';
import { TimeConst } from '../../Util/DateUtil';
import { CallBackHandler } from '../Model/PoolObj/CallBackHandler';
import { LogUtil } from '../../Util/LogUtil';
import { TimeCountType } from '../../Game/Config/GameEnum';
const { ccclass } = _decorator;
/* eslint-disable */
@ccclass('TimeControler')
export class TimeControler extends Component {
  /** 现在的时间 */
  nowTime: number = 0;
  /** 当天的零点 */
  todayZero: number = 0;
  /** 过零点的回调 */
  private callbacks: Map<string, CallBackHandler> = new Map();
  /** 设定时间点的回调 */
  private timeCountFunc: Map<TimeCountType, [number, CallBackHandler, boolean]> = new Map();
  /** 倒计时时回调 */
  private timeCountDownFunc: Map<TimeCountType, [number, CallBackHandler, number]> = new Map();

  protected start() {
    const time = new Date();
    this.nowTime = time.getTime();
    this.todayZero = time.setHours(0, 0, 0, 0);
    this.newDay();
  }

  /** 设置游戏时间 */
  resetGameTime(time: number) {
    this.nowTime = time;
    const date = new Date(this.nowTime);
    this.todayZero = date.setHours(0, 0, 0, 0);
  }

  private _time: number = 0;
  protected update(dt: number): void {
    this.nowTime += Math.floor(dt * TimeConst.Seconds);
    if (this.nowTime >= this.todayZero + TimeConst.Day) {
      const time = new Date();
      this.todayZero = time.getTime() - time.getHours() * TimeConst.Hours - time.getMinutes() * TimeConst.Minutes - time.getSeconds() * TimeConst.Seconds - time.getMilliseconds();
      this.newDay();
    }
    this._time += dt;
    if (this._time < 1) return;
    this._time = 0;
    this.checkTimeCount();
  }

  /** 绑定零点回调事件 */
  registerNewDay(type: string, callback: (...args: any[]) => void, target?: any, ...params: any[]) {
    if (this.callbacks.has(type)) {
      throw new Error('重复绑定时间回调函数');
    }
    const handler = CallBackHandler.pop(callback, target, ...params);
    this.callbacks.set(type, handler);
  }

  unRegisterNewDay(type: string) {
    if (!this.callbacks.has(type)) {
      LogUtil.e('TimeControl:' + type, '没有绑定时间回调函数');
      return;
    }
    this.callbacks.get(type).release();
    this.callbacks.delete(type);
  }

  newDay() {
    this.callbacks.forEach((handler) => {
      handler.activate();
    });
  }

  /** 绑定全局计时器
   * @param type 计时器类型
   * @param time 多长时间回调一次
   * @param callback 回调函数
   * @param target 回调函数的this对象
   * @param loop 回调次数 -1表示无限循环
   * @param params 回调函数的参数
   */
  registerTimeCountDown(type: TimeCountType, time: number, callback: (...args: any[]) => void, target?: any, loop: number = -1, ...params: any[]) {
    //至少执行一次
    if (loop == 0) return;
    if (this.timeCountDownFunc.has(type)) {
      LogUtil.e('TimeControl:' + type, '重复绑定时间回调函数');
      return;
    }
    const handler = CallBackHandler.pop(callback, target, ...params);
    time += this.nowTime;
    this.timeCountDownFunc.set(type, [time, handler, loop]);
  }

  /** 绑定全局计时器
   * @param type 计时器类型
   * @param time 计时时间（时间点，时间戳 （毫秒））
   * @param callback 回调函数
   * @param target 回调函数的this对象
   * @param loop 是否循环
   * @param params 回调函数的参数
   */
  registerTimeCount(type: TimeCountType, time: number, callback: (...args: any[]) => void, target?: any, loop: boolean = false, ...params: any[]) {
    if (this.timeCountFunc.has(type)) {
      LogUtil.e('TimeControl:' + type, '重复绑定时间回调函数');
      return;
    }
    const handler = CallBackHandler.pop(callback, target, ...params);
    this.timeCountFunc.set(type, [time, handler, loop]);
  }

  unRegisterTimeCount(type: TimeCountType) {
    if (!this.timeCountFunc.has(type)) {
      LogUtil.e('TimeControl:' + type, '没有绑定时间回调函数');
      return;
    }
    this.timeCountFunc.get(type)[1].release();
    this.timeCountFunc.delete(type);
  }

  checkTimeCount() {
    let keysToRemove: TimeCountType[] = [];
    this.timeCountFunc.forEach(([time, handler, loop], key) => {
      if (this.nowTime >= time) {
        handler.execute();
        if (!loop) keysToRemove.push(key);
      }
    });
    keysToRemove.forEach((key) => {
      this.timeCountFunc.delete(key);
    });

    keysToRemove.length = 0;
    this.timeCountDownFunc.forEach((value, key) => {
      const [time, handler, loop] = value;
      if (this.nowTime >= time) {
        handler.execute();
        if (loop - 1 == 0) {
          keysToRemove.push(key);
        } else if (loop > 0) {
          value[2] = loop - 1;
        }
      }
    });
    keysToRemove.forEach((key) => {
      this.timeCountDownFunc.delete(key);
    });
  }
}
